package com.adv.ems.filters.original.before;

import com.adv.ems.db.entity.CollectPointDO;
import com.adv.ems.filters.EnergyDataBaseFilter;
import com.adv.ems.filters.dto.FilterParam;
import com.adv.ems.filters.original.dto.EnergyDataOriginalBeforeDTO;
import com.adv.ems.manager.CollectPointManager;
import com.adv.ems.model.vo.ResultVO;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
public class CollectPointUpdateLastInfoBeforeFilter extends EnergyDataBaseFilter<EnergyDataOriginalBeforeDTO, Boolean> implements SmartInitializingSingleton {
    @Resource
    CollectPointManager collectPointManager;
    private Map<Long, CollectPointDO> pointUpdateTask = new ConcurrentHashMap<>();

    @Override
    protected String getFilterName() {
        return "采集点实时数据更新";
    }

    @Override
    protected double getOrder() {
        return 3;
    }

    @Override
    protected boolean isBefore() {
        return true;
    }

    @Override
    protected String getType() {
        return EnergyDataOriginalBeforeDTO.class.getName();
    }

    @Override
    protected ResultVO<Boolean> handle(FilterParam<EnergyDataOriginalBeforeDTO> param) {
        Map<Long, CollectPointDO> pointDOMap = collectPointManager.getAllMap();
        Map<Long, List<EnergyDataOriginalBeforeDTO>> group = param.getList().stream().sorted(Comparator.comparing(EnergyDataOriginalBeforeDTO::getColDate).reversed()).collect(Collectors.groupingBy(EnergyDataOriginalBeforeDTO::getCollectPointId));
        for (Map.Entry<Long, List<EnergyDataOriginalBeforeDTO>> entry : group.entrySet()) {
            if (entry.getValue().isEmpty()) {
                continue;
            }
            CollectPointDO point = pointDOMap.get(entry.getKey());
            EnergyDataOriginalBeforeDTO data = entry.getValue().get(0);
            if (point.getLastUploadTime() == null || point.getLastUploadTime().before(data.getColDate())) {
                point.setLastUploadTime(data.getColDate());
                point.setLastUploadRealValue(data.getRealValue());
                pointUpdateTask.put(point.getId(), point);
            }
        }
        return ResultVO.success();
    }

    private void syncUpdatePointLastUpdateTime() {
        while (!pointUpdateTask.isEmpty()) {
            Long pointId = pointUpdateTask.keySet().iterator().next();
            CollectPointDO point = pointUpdateTask.get(pointId);
            collectPointManager.updateLastUploadInfo(point.getId(), point.getLastUploadTime(), point.getLastUploadRealValue());
            pointUpdateTask.remove(pointId);
        }
        try {
            Thread.sleep(1000 * 60);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void afterSingletonsInstantiated() {
        new Thread(() -> {
            while (!Thread.interrupted()) {
                syncUpdatePointLastUpdateTime();
            }
        }).start();
    }
}
